﻿using mozhi.smarterp.Business.Enums;
using mozhi.smarterp.Business.Purchases.Repositories;
using Mozhi.Abp.Domain.AuthorCenter;
using Mozhi.Abp.Domain.BasicData;
using Mozhi.Abp.Domain.BasicData.Repositories;
using System;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Guids;

namespace mozhi.smarterp.Business.Purchases.Services
{
    public class PurchaseRequisitionManager : DocumentManagerBase<PurchaseRequisition ,Guid>
    {
        private IGuidGenerator _guidGenerator;
        private IProductRepository _productRepository;
        private IDepartmentRepository _departmentRepository;
        private IEmployeeRepository _employeeRepository;
        private ITaxRateRepository _taxRateRepository;
        private ICurrencyRepository _currencyRepository;
        private IUnitRepository _unitRepository;
        private IProductAuxiliaryUnitRepository _productAuxiliaryUnitRepository;
        private ISupplierRepository _supplierRepository;
        private IPurchaseRequisitionOrderRepository _requisitionOrderRepository;

        public PurchaseRequisitionManager(IPurchaseRequisitionRepository repository, IGuidGenerator guidGenerator,
            IProductRepository productRepository, IDepartmentRepository departmentRepository, IEmployeeRepository employeeRepository,
            ICurrencyRepository currencyRepository, IUnitRepository unitRepository, IProductAuxiliaryUnitRepository productAuxiliaryUnitRepository,
            ISupplierRepository supplierRepository , INumberGeneratorRepository numberGeneratorRepository , ITaxRateRepository taxRateRepository , IPurchaseRequisitionOrderRepository requisitionOrderRepository)
            :base(repository , numberGeneratorRepository , DocumentType.PurchaseRequisition)
        {
            _repository = repository;
            _guidGenerator = guidGenerator;
            _productRepository = productRepository;
            _departmentRepository = departmentRepository;
            _employeeRepository = employeeRepository;
            _currencyRepository = currencyRepository;
            _unitRepository = unitRepository;
            _productAuxiliaryUnitRepository = productAuxiliaryUnitRepository;
            _supplierRepository = supplierRepository;
            _taxRateRepository = taxRateRepository;
            _requisitionOrderRepository = requisitionOrderRepository;
        }

        public async Task<PurchaseRequisition> GetAysnc(Guid? id, Guid? departmentId, DateTime date, string comment, ProductType productType,
            Guid currencyId, decimal exchangeRate, bool includeTax, Guid? applicantId)
        {
            var department = departmentId.HasValue ? await _departmentRepository.GetAsync(departmentId.Value) : null;

            var applicant = applicantId.HasValue ? await _employeeRepository.GetAsync(applicantId.Value) : null;

            var currency = await _currencyRepository.GetAsync(currencyId);

            if (currency != null)
                currency.SetExchangeRate(exchangeRate);

            PurchaseRequisition requisition;

            if (id.HasValue)
            {
                requisition = await _repository.GetAsync(id.Value);

                if (requisition == null)
                    throw new UserFriendlyException($"申请单：{id.Value}不存在", "100000");

                //审核了的单据就不允许更改其他信息了
                if (requisition.Status == DocumentStatusType.PendingApproval)
                    return requisition;


                requisition.Change(requisition.Number, date, comment, productType, currency, includeTax, department, applicant);
            }
            else
            {
                var number = await GetNextNumberAsync();

                var count = await _repository.GetCountAsync(number, id);

                if (count > 0)
                    throw new UserFriendlyException($"申请单编号：{number}已存在", "100000");

                requisition = new PurchaseRequisition(_guidGenerator.Create(), number, date, comment, productType, currency, includeTax, department, applicant);

                requisition.SetStatus(DocumentStatusType.Creation);
            }

            return requisition;
        }

        public async Task<PurchaseRequisitionItem> GetItemsAsync(Guid? id, Guid productId, Guid requisitionUnitId, decimal requisitionQuantity, decimal? approveQuantity, decimal price , DateTime? requireDate, Guid? taxRateId, Guid? supplierId, string remark)
        {
            var product = await _productRepository.GetAsync(productId);

            if (!supplierId.HasValue)
                supplierId = product.DefaultSupplierId;

            var requisitionUnit = await _unitRepository.GetAsync(requisitionUnitId);

            var supplier = supplierId.HasValue ? await _supplierRepository.GetAsync(supplierId.Value) : null;

            var auxiliaryUnit = await _productAuxiliaryUnitRepository.GetAsync(productId, requisitionUnitId);

            var taxrate = taxRateId.HasValue ? await _taxRateRepository.GetAsync(taxRateId.Value) : null;

            id = id ?? _guidGenerator.Create();

            var item = new PurchaseRequisitionItem(id.Value, product, requisitionUnit, auxiliaryUnit, requisitionQuantity, approveQuantity ?? requisitionQuantity, price , taxrate , requireDate, supplier, remark);

            return item;
        }

        public async Task<PurchaseRequisition> UpdateStatusAsync(Guid id , DocumentStatusType status)
        {
            var requisition = await _repository.GetAsync(id, false);

            if (requisition == null)
                throw new UserFriendlyException($"采购申请单：{id}不存在", "100000");
            //撤销审核
            if(requisition.Status == DocumentStatusType.Approved && status == DocumentStatusType.PendingApproval)
            {
                var requistionOrderCount = await _requisitionOrderRepository.GetCountAsync(requisition.Id , null , null , null );

                if (requistionOrderCount > 0)
                    throw new UserFriendlyException($"采购申请单：{requisition.Number}已关联订单，不允许反审核", "100000");
            }

            requisition.SetStatus(status);

           return requisition;
        }
    }
}
